home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / wnos / wn941101 / forward.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-07  |  23.2 KB  |  850 lines

  1. /* Some of the code in this file was originally based on the following file:
  2.  * gateway.c : Paul Healy, EI9GL, 900818
  3.  *
  4.  * Rewrote forwarding mechanism to use "X-Forwarded-To" paradigm instead of
  5.  * "X-BBS-To", added timer support, etc.  Anders Klemets, SM0RGV, 901009.
  6.  */
  7. #include <stdio.h>
  8. #include <string.h>
  9. #include <ctype.h>
  10. #include <time.h>
  11. #include "global.h"
  12. #include "config.h"
  13. #include "bm.h"
  14. #include "mailbox.h"
  15. #include "smtp.h"
  16. #include "cmdparse.h"
  17. #include "proc.h"
  18. #include "socket.h"
  19. #include "timer.h"
  20. #include "usock.h"
  21. #include "netuser.h"
  22. #include "ax25.h"
  23. #include "netrom.h"
  24. #include "nntp.h"
  25. #include "nr4.h"
  26. #include "files.h"
  27.  
  28. #define ISPROMPT(s)    (strlen(s) > 1 && s[strlen(s)-2] == '>')
  29. static struct timer fwdtimer;
  30.  
  31. static char *findident __ARGS((char *str, int n, char *result));
  32. static void near sendmsg __ARGS((struct mbx *m,int msgn));
  33. static char * near mbxtime __ARGS((char *line));
  34. static int fwdinit __ARGS((struct mbx *m));
  35. static char *fwdanybbs __ARGS((struct mbx *m));
  36. static int timeok __ARGS((char *line));
  37. static void fwdtick __ARGS((void *v));
  38. static int isconnbbs __ARGS((struct mbx *m));
  39. static void startfwd __ARGS((int a,void *v1,void *v2));
  40. static int openconn __ARGS((int argc,char *argv[],void *p));
  41. static int near sendmsgtobbs __ARGS((struct mbx *m,int msgn,char *dest,int bulletin));
  42. static int makecl __ARGS((struct mbx *m,int msgn,char *dest,char *line,char *subj,int bulletin));
  43. static char *grabtext __ARGS((char *from,char *to,int marker));
  44.  
  45. char *FNic = NULLCHAR;
  46. char *FInfo = NULLCHAR;
  47. /***************************************************************************
  48.    findident copies the 'n'th alphanumeric sequence from 'str' to result.
  49.    It returns a ptr to result. It returns "\0" for missing identifier etc.
  50.    Uses isalnum macro to decide on alphanumeric/non-alnum status.
  51. */
  52. static char *
  53. findident(str, n, result)
  54. char *str, *result;
  55. int n;
  56. {
  57.    int count; /* current identifier */
  58.    count = 0;
  59.    *result = '\0';
  60.    while ( (count<n) && (*str!='\0') ) { /* Process alnum or non alnum seq */
  61.       while ( (*str!='\0') && (!isalnum(*str)) ) /* Get rid of ';:.@%"# etc */
  62.          str++;
  63.       if ( (str!='\0') && isalnum(*str) ) { /* this is an alnum seq */
  64.          count++;
  65.          while ( (*str!='\0') && (isalnum(*str) || (*str=='_')) )
  66.             if (count==n)
  67.                *result++ = *str++;
  68.             else str++;
  69.          if (count==n)
  70.             *result = '\0';
  71.          }
  72.       }
  73.    return result;
  74. }
  75. /**************************************************************************/
  76.  
  77. static void near
  78. sendmsg(struct mbx *m,int msgn)
  79. {
  80.     char buf[LINELEN], tb[LINELEN], *cp;
  81.     char *from;
  82.     int len = 0;
  83.     long cnt = m->mbox[msgn].size;
  84.  
  85.     fseek(m->mfile,m->mbox[msgn].start,0);
  86.     *from = '\0';
  87.     *tb = '\0';
  88.     for(;;) {
  89.         /* Swallow all header lines */
  90.         if(fgets(buf,sizeof(buf),m->mfile) == NULLCHAR)
  91.             break;
  92.         cnt -= strlen(buf);
  93.  
  94.         /* Find and save first date/time and ID */
  95.         if(*tb == NULL)
  96.              if((cp = strchr(buf,';')) != NULLCHAR)
  97.                   strcpy(tb,cp+1);
  98.         
  99. /* neu */        
  100.     switch(htype(buf)) {
  101.     case FROM:
  102.         if((cp = getaddress(buf,0)) != NULLCHAR) {
  103.             strcpy(from,cp);
  104.         }
  105.         if((cp = strchr(from,'@')) != NULLCHAR)
  106.             *cp = '\0';
  107.             strupr(from);
  108.             break;
  109.     }
  110.  
  111.         if(*buf == '\n'){     /* last header line */
  112.             /* Stick our header in  */
  113.             pax25(buf,Mycall);
  114.             if((cp = strchr(buf,'-')) != NULLCHAR)
  115.                 *cp = '\0'; /* remove SSID  */
  116.         usflush(m->user);
  117.         pause(3000L);
  118.             usprintf(m->user,"R:%s @%s.%s [%s]",
  119.                 mbxtime(tb),buf,
  120.                 FNic != NULLCHAR ? FNic : buf,
  121.                 FInfo != NULLCHAR ? FInfo : Version);
  122.         usflush(m->user);
  123.         pause(4000L);
  124.             usprintf(m->user,"\nde %s @ %s.%s\n\n",from,buf,FNic);
  125.                 
  126.             usflush(m->user);
  127.             pause(4000L);
  128.             break;
  129.         }
  130.     }
  131.  
  132.             
  133.     do {
  134.         /* the rest of the message is treated below */
  135.         len = (int)min(cnt,sizeof(buf)-1);
  136.         if(fread(buf,1,len,m->mfile) != len)
  137.             break;
  138.         cnt -= len;
  139.         buf[len] = '\0';
  140.         usputs(m->user,buf);
  141.     } while(cnt);
  142. }
  143.  
  144. /* Parse a line for date and time in Arpanet format
  145.  * (Day, day Month year hh:mm:ss Zone) and return it in mailbox format
  146.  * (yymmdd/hhmmz)
  147.  */
  148. static char * near
  149. mbxtime(char *line)
  150. {
  151.          time_t temp;
  152.          struct tm *ltm;
  153.          static char buf[13];
  154.  
  155.          /* get time from first line */
  156. #if (defined(NNTP) && defined(MAILBOX))
  157.          temp = articletime(line);
  158. #endif
  159.          /* convert unixtime to string */
  160.          ltm = localtime(&temp);
  161.  
  162.          sprintf(buf,"%02d%02d%02d/%02d%02dz",
  163.                 ltm->tm_year,
  164.                 ltm->tm_mon + 1,
  165.                 ltm->tm_mday,
  166.                 ltm->tm_hour,
  167.                 ltm->tm_min);
  168.  
  169.      return buf;
  170. }
  171.      
  172. static char *
  173. grabtext(from, to, marker)
  174. char *from, *to;
  175. int marker;
  176. {
  177.    while (*from!=marker)
  178.       *to++ = *from++;
  179.    *to = '\0';
  180.    return from+1;
  181. }
  182.  
  183. /* Makes a command line and returns -1 if the message cannot be sent. */
  184. static int
  185. makecl(m, msgn, dest, line, subj, bulletin)
  186. struct mbx *m;
  187. int msgn;        /* Message number */
  188. char *dest;        /* Destination address to use instead of To: line */
  189. char *line, *subj;    /* Buffers to keep command line and subject */
  190. int bulletin;        /* True if message is in public message area */
  191. {
  192.    char bid[LINELEN], to[LINELEN], atbbs[LINELEN], from[LINELEN],
  193.     buf[LINELEN], *cp;
  194.    if(m->mfile == NULLFILE)
  195.     return -1;
  196.    if(!bulletin && (m->mbox[msgn].status & BM_READ))
  197.     return -1;    /* the message was already read */
  198.    fseek(m->mfile,m->mbox[msgn].start,0);
  199.    *bid = *to = *atbbs = *from = '\0';
  200.    if(subj != NULLCHAR)
  201.     *subj = '\0';
  202.    m->stype = bulletin ? 'B' : 'P';    /* default to SB or SP */
  203.    while (fgets(buf,sizeof(buf),m->mfile)) {
  204.       if (buf[0] == '\n')
  205.          break; /* envelope finished */
  206.       switch (htype(buf)) {
  207.       case TO:
  208.         /* The following code tries to parse "To: " lines where the
  209.          * address looks like any of the following: "to@atbbs",
  210.          * "<to@atbbs>", "<to%atbbs@host>" and with possible spaces
  211.          * surrounding the '<>' characters.
  212.          */
  213.         if((cp = getaddress(buf,0)) == NULLCHAR)
  214.         break;
  215.         strcpy(to,cp);
  216.         if((cp = strchr(to,'%')) != NULLCHAR) { /* look for a '%' */
  217.          strcpy(atbbs,cp + 1);
  218.          *cp = '\0';    /* "to" ends at the '%' character */
  219.         }
  220.         else {    /* no '%' but maybe a '@'? */
  221.          if((cp = strchr(to,'@')) != NULLCHAR) {
  222.               strcpy(atbbs,cp + 1);
  223.               *cp = '\0';    /* "to" ends at the '@' character */
  224.          }
  225.         }
  226.         if(*atbbs != '\0')        /* either '%' or '@' found */
  227.          /* cut "atbbs" at the first '@' character */
  228.          for(cp = atbbs; *cp != '\0'; ++cp)
  229.               if(*cp == '@') {
  230.                *cp = '\0';
  231.                break;
  232.               }
  233.         /* "to" or "atbbs" should not be more than 6 characters (ALEN).
  234.          * If "to" is too long, it might simply be because the area name
  235.          * is longer than 6 characters, but it might also be because
  236.          * the address on the To: line is in an obscure format that we
  237.          * failed to parse (eg '!' character notation.)
  238.          */
  239.         if(strlen(to) > ALEN) {
  240.         /* Play safe and set "to" and "atbbs" to the area name */
  241.         strcpy(to,m->area);
  242.         strcpy(atbbs,m->area);
  243.               }
  244.         if(*atbbs == '\0')
  245.         strcpy(atbbs,to);
  246.               to[ALEN] = '\0';
  247.         /* Only if the BBS supports "hierarchical routing designators"
  248.          * is the atbbs field allowd to be longer than 6 characters and
  249.          * have dots in it.
  250.          */
  251.         if((m->sid & MBX_HIER_SID) == 0) {
  252.          atbbs[ALEN] = '\0';    /* 6 character limit */
  253.          if((cp = strchr(atbbs,'.')) != NULLCHAR)
  254.               *cp = '\0';    /* cut "atbbs" at first dot */
  255.         }
  256.             break;
  257.       case MSGID:
  258.         /* The following code distinguishes between two different types
  259.          * of Message-IDs: <abcde@callsign.bbs> and <abcde@host.domain>.
  260.          * The first type is converted to $abcde and the second to
  261.          * $abcde_host.domain. This preserves compability with BBSes.
  262.          */
  263.         if((cp = getname(buf)) == NULLCHAR)
  264.          break;
  265.         bid[0] = '$';
  266.         strcpy(&bid[1],cp);
  267.               cp = strchr(bid,'@');
  268.         /* A trailing ".bbs" indicates that the Message-ID was generated
  269.          * from a BBS style message, and not a RFC-822 message.
  270.          */
  271.         if(cp != NULLCHAR && stricmp(&bid[strlen(bid) - 4], ".bbs") == 0)
  272.         *cp = '\0';
  273.         else
  274.         *cp = '_';
  275.         bid[13] = '\0';    /* BIDs should be no longer than 13 bytes */
  276.               break;
  277.       case SUBJECT:
  278.         if(subj != NULLCHAR)
  279.               (void) grabtext(buf+9, subj, '\n');
  280.             break;
  281.       case FROM:
  282.         if((cp = getaddress(buf,0)) != NULLCHAR) {
  283.         findident(cp, 1, from);        /* cp points to from@domain */
  284.         from[ALEN] = '\0';    /* 6 character limit */
  285.         }
  286.             break;
  287.       case XFORWARD:
  288.         if((cp = getaddress(buf,0)) == NULLCHAR)
  289.          break;
  290.         if(stricmp(m->name,cp) == 0)
  291.         /* This message has already been forwarded, abort */
  292.         return -1;
  293.         break;
  294.       case BBSTYPE:
  295.         m->stype = buf[16];
  296.         break;
  297.       default:
  298.         break;
  299.       }
  300.    }
  301.    /* Check for an invalid RFC-822 header */
  302.    if((to[0] == '\0' && ((dest != NULLCHAR && *dest == '\0') ||
  303.       dest == NULLCHAR)) || from[0] == '\0')
  304.     return -1;
  305.  
  306.    if(line != NULLCHAR) {
  307.     if(dest != NULLCHAR && *dest != '\0'){
  308.          /* strip off hierarchical routing designators from the predefined
  309.           * destination address if they are not supported
  310.           */
  311.          if((m->sid & MBX_HIER_SID) == 0 && (cp = strchr(dest,'.')) !=
  312.            NULLCHAR)
  313.         *cp = '\0';
  314.          sprintf(line, "S%c %s < %s ", m->stype, dest, from);
  315.     }
  316.     else
  317.          sprintf(line, "S%c %s @ %s < %s ", m->stype, to, atbbs, from);
  318.     if(bulletin & (m->sid & MBX_SID))
  319.          strcat(line,bid);
  320.     strcat(line,"\n");
  321.    }
  322.    return 0;
  323. }
  324.  
  325. static int near                /* 0 = ok, -1 = problem so disc */
  326. sendmsgtobbs(
  327. struct mbx *m,
  328. int msgn,
  329. char *dest,        /* Optional destination address to override To: line */
  330. int bulletin)
  331. {
  332.     int result = -1;
  333.     char cp = 26;    /* End of Msg changed to CTRL-Z - DB3FL.910328 */
  334.     char line[MBXLINE], subj[256];
  335.  
  336.     if(makecl(m,msgn,dest,line,subj,bulletin) == -1)
  337.         return 0;            /* do not forward this particular message */
  338.  
  339.     usputs(m->user,line);             /* Send mail offer to bbs */
  340.     rip(line);
  341.     usflush(m->user);
  342.  
  343.     if (recvline (m->user, m->line, MBXLINE) != -1 ) {
  344.         if (*m->line == 'O' || *m->line == 'o' || (m->sid & MBX_SID) == 0) {
  345.             /* Got 'OK' or any line if the bbs is unsofisticated */
  346.             usprintf(m->user,"%s\n", subj);
  347.             sendmsg(m,msgn);    /* send the message */
  348.             usprintf(m->user,"%c\n",cp);    /* End of Msg changed to CTRL-Z - DB3FL.910328 */
  349.             usflush(m->user);
  350.             /* get F> for a good deliver */
  351.             while (recvline (m->user, m->line, MBXLINE) != -1 )
  352.                 if (ISPROMPT(m->line)) {
  353.                     log(m->user,"MBOX bbs mail sent: %s ", line);
  354.                     if(bulletin)
  355.                         m->mbox[msgn].status |= BM_FORWARDED;
  356.                     else
  357.                         m->mbox[msgn].status |= BM_DELETE;
  358.                     m->change = 1;
  359.                     result = 0;
  360.                     break;
  361.                 }
  362.         } else { /* OK response not received from bbs */
  363.             if (*m->line == 'N' || *m->line == 'n') { /* 'NO' respone */
  364.                 log(m->user,"MBOX bbs mail refused: %s\n-> %s",line,m->line);
  365.                 /* Mark refused message as forwarded if it is a bulletin.
  366.                  * The message was probably a duplicate. Non-bulletin
  367.                  * messages are sent without BID, so they cannot be detected
  368.                  * as duplicates. The reason why it was refused is probably
  369.                  * because the address was invalid. Retry later.
  370.                  */
  371.                 if(bulletin){
  372.                     m->mbox[msgn].status |= BM_FORWARDED;
  373.                     m->change = 1;
  374.                 }
  375.             }
  376.             /* should get a F> here */
  377.             while (recvline (m->user, m->line, MBXLINE) != -1)
  378.                 if (ISPROMPT(m->line)) {
  379.                     result = 0;
  380.                 break;
  381.             }
  382.        }
  383.    }     /* OK or NO here */
  384.    return result;
  385. }
  386.  
  387.  
  388. /* This is the main entry point for reverse forwarding. It is also used
  389.  * for normal, "forward", forwarding.
  390.  */
  391. int
  392. dorevfwd(argc,argv,p)
  393. int argc;
  394. char *argv[];
  395. void *p;
  396. {
  397.     char oldarea[64], *cp;
  398.     struct mbx *m;
  399.     int i, bulletin, err = 0;
  400.     m = (struct mbx *)p;
  401.     log(m->user,"MBOX forwarding mail to: %s ", m->name);
  402.     /* indicate we are doing reverse forwarding, if we are not already
  403.      * doing normal forwarding.
  404.      */
  405.     if(m->state != MBX_FORWARD)
  406.         m->state = MBX_REVFWD;
  407.     if(fwdinit(m) != -1) {
  408.         strcpy(oldarea,m->area);
  409.         while(!err && fgets(m->line,MBXLINE,m->tfile) != NULLCHAR) {
  410.             if(*m->line == '-')    /* end of record reached */
  411.                 break;
  412.             rip(m->line);        /* adds extra null at end */
  413.             cp = strchr(m->line,' '); /* remove trailing blanks */
  414.             if(cp != NULLCHAR)
  415.                 *cp = '\0';
  416.             if((cp = strchr(m->line,'\t')) != NULLCHAR)
  417.                 *cp = '\0';
  418.             if(*m->line == '\0' || *m->line == '.')
  419.                 continue;
  420.             changearea(m,m->line);
  421.             bulletin = isarea(m->line);    /* public area */
  422.             /* get the optional destination field, cp will point
  423.              * at null byte if it is missing.
  424.              */
  425.             cp = &m->line[strlen(m->line)] + 1;
  426.             while(*cp != '\0' && isspace(*cp)) /* strip blanks */
  427.                  ++cp;
  428.             for(i=1; i<=m->nmsgs; i++)
  429.                 if(sendmsgtobbs(m, i, cp, bulletin) == -1) {
  430.                     err = 1;    /* abort */
  431.                     break;
  432.                 }
  433.         }
  434.         fclose(m->tfile);
  435.         m->tfile = NULLFILE;
  436.         if(*oldarea != '\0')
  437.             changearea(m,oldarea);
  438.     }
  439.     if(m->state == MBX_FORWARD)
  440.         return 0;
  441.     tprintf("*** Done\n");
  442.     if((m->sid & MBX_RLI_SID))    /* disconnect if it is a W0RLI bbs */
  443.         return domboxbye(0,NULL,m);
  444.     return 0;
  445. }
  446.  
  447. /* Read the forward file for a record for the connected BBS. If found,
  448.  * return 1 if this is the right time to forward, m->tfile is left pointing
  449.  * at the first message area to be forwarded.
  450.  */
  451. static int
  452. fwdinit(m)
  453. struct mbx *m;
  454. {
  455.     char host[80];
  456.     int start = 1;
  457.     if((m->tfile = fopen(Forwardfile,READ_TEXT)) == NULLFILE)
  458.         return -1;
  459.     while(fgets(m->line,MBXLINE,m->tfile) != NULLCHAR) {
  460.         if(*m->line == '\n')
  461.             continue;
  462.         /* lines starting with '-' separate the forwarding records */
  463.         if(*m->line == '-') {
  464.             start = 1;
  465.             continue;
  466.         }
  467.         if(start) {
  468.             start = 0;
  469.             /* get the name of this forwarding record */
  470.             findident(m->line,1,host);
  471.             if(stricmp(m->name,host) == 0) {
  472.                 if(!timeok(m->line))
  473.                     break;
  474.                 /* eat the connect command line */
  475.                 fgets(m->line,MBXLINE,m->tfile);
  476.                 return 0;
  477.             }
  478.         }
  479.     }
  480.     fclose(m->tfile);
  481.     m->tfile = NULLFILE;
  482.     return -1;
  483. }
  484. /* Read the forward file for a record for the connected BBS. If found,
  485.  * determine if this is the right time to forward, and return the command
  486.  * line to establish a forwarding connection. m->tfile is left pointing
  487.  * at the first message area to be forwarded.
  488.  */
  489. static char *
  490. fwdanybbs(m)
  491. struct mbx *m;
  492. {
  493.     char host[80];
  494.     int start = 1;
  495.     if(m->tfile == NULLFILE && (m->tfile = fopen(Forwardfile,READ_TEXT))
  496.                     == NULLFILE)
  497.         return NULLCHAR;
  498.     while(fgets(m->line,MBXLINE,m->tfile) != NULLCHAR) {
  499.         if(*m->line == '\n')
  500.             continue;
  501.         /* lines starting with '-' separate the forwarding records */
  502.         if(*m->line == '-') {
  503.             start = 1;
  504.             continue;
  505.         }
  506.         if(start) {
  507.             start = 0;
  508.             /* get the name of this forwarding record */
  509.             findident(m->line,1,host);
  510.             strcpy(m->name,host);
  511.             if(!timeok(m->line))
  512.                 continue;    /* too late or too early */
  513.             /* get the connect command line */
  514.             fgets(m->line,MBXLINE,m->tfile);
  515.             return strxdup(m->line);
  516.         }
  517.     }
  518.     fclose(m->tfile);
  519.     m->tfile = NULLFILE;
  520.     return NULLCHAR;
  521. }
  522.  
  523. /* get any groups of four digits that specify the begin and ending hours of
  524.  * forwarding. Returns 1 if forwarding may take place.
  525.  */
  526. static int
  527. timeok(line)
  528. char *line;
  529. {
  530.     char hours[80], *now;
  531.     long t;
  532.     int t1, t2, pos = 2;
  533.     findident(line,pos++,hours);
  534.     if(*hours == '\0')
  535.         return 1;    /* no digits default to 0023, ie. anytime */
  536.     time(&t);
  537.     now = ctime(&t) + 11;
  538.     *(now + 2) = '\0';
  539.     while(*hours != '\0') {
  540.         t1 = (*hours - '0') * 10 + (*(hours+1) - '0');
  541.         t2 = (*(hours+2) - '0') * 10 + (*(hours+3) - '0');
  542.         if(atoi(now) >= t1 && atoi(now) <= t2)
  543.             return 1;        /* right in time */
  544.         findident(line,pos++,hours);    /* get next group if any */
  545.     }
  546.     return 0;    /* too early or too late */
  547. }
  548.  
  549. int
  550. dombtimer(argc,argv,p)
  551. int argc;
  552. char *argv[];
  553. void *p;
  554. {
  555.     if(argc < 2){
  556.         tprintf("Forwarding timer: %lu/%lu\n",
  557.         read_timer(&fwdtimer) * MSPTICK/1000,
  558.         dur_timer(&fwdtimer) * MSPTICK/1000);
  559.         return 0;
  560.     }
  561.     fwdtimer.func = (void (*)())fwdtick;/* what to call on timeout */
  562.     fwdtimer.arg = NULL;        /* dummy value */
  563.     set_timer(&fwdtimer,atol(argv[1])*1000); /* set timer duration */
  564.     start_timer(&fwdtimer);        /* and fire it up */
  565.     return 0;
  566. }
  567.  
  568. int
  569. dombkick(argc,argv,p)
  570. int argc;
  571. char *argv[];
  572. void *p;
  573. {
  574.     fwdtick(NULL);
  575.     return 0;
  576. }
  577.  
  578. /* called when the forward timer expires or explicitly by dombkick() */
  579. static void
  580. fwdtick(v)
  581. void *v;
  582. {
  583.     char *cc, *cp;
  584.     struct mbx *m;
  585.     int i, bulletin, skip = 0;
  586.     /* restart the timer */
  587.     start_timer(&fwdtimer);
  588.     if((m = newmbx()) == NULLMBX)
  589.         return;
  590.     m->user = Curproc->output;
  591.     m->state = MBX_TRYING;
  592.     while((cc = fwdanybbs(m)) != NULLCHAR) {
  593.         if(isconnbbs(m)) /* already connected to this BBS, skip it */
  594.             skip = 1;
  595.         while(fgets(m->line,MBXLINE,m->tfile) != NULLCHAR) {
  596.             if(*m->line == '-') {    /* end of record reached */
  597.                 skip = 0;
  598.                 break;
  599.             }
  600.             if((cp = strchr(m->line,' ')) != NULLCHAR)
  601.                 *cp = '\0';
  602.             if((cp = strchr(m->line,'\t')) != NULLCHAR)
  603.                 *cp = '\0';
  604.             if(skip || *m->line == '\0' || *m->line == '.')
  605.                 continue;
  606.             rip(m->line);
  607.             changearea(m,m->line);
  608.             bulletin = isarea(m->line);    /* public area */
  609.             /* check if there are any messages in this area
  610.              * that need to be forwarded.
  611.              */
  612.             for(i=1; i<=m->nmsgs; i++)
  613.                 if(makecl(m, i, NULLCHAR, NULLCHAR, NULLCHAR,
  614.                    bulletin) == 0) {
  615.                     newproc("Mbox forwarding", 2048,
  616.                         startfwd, 0, (void *)cc,
  617.                         (void *)strxdup(m->name),0);
  618.                     skip = 1;
  619.                     cc = NULLCHAR;
  620.                     break;
  621.                 }
  622.         }
  623.         xfree(cc);
  624.     }
  625.     exitbbs(m);
  626. }
  627.  
  628. /* returns 1 if m->name matches the name of another connected mailbox. */
  629. static int
  630. isconnbbs(m)
  631. struct mbx *m;
  632. {
  633.     int i;
  634.     for(i = 0; i < NUMMBX; ++i)
  635.         if(Mbox[i] != NULLMBX && Mbox[i] != m &&
  636.             stricmp(m->name,Mbox[i]->name) == 0)
  637.                 return 1;
  638.     return 0;
  639. }
  640.  
  641. /* possible commands on the command line in the forwarding file */
  642. static struct cmds cfwdcmds[] = {
  643.     "tcp",        openconn,    0, 0, NULLCHAR,
  644.     "telnet",    openconn,    0, 0, NULLCHAR,
  645. #ifdef AX25
  646.     "ax25",        openconn,    0, 0, NULLCHAR,
  647.     "connect",    openconn,    0, 0, NULLCHAR,
  648. #endif
  649. #ifdef NETROM
  650.     "netrom",    openconn,    0, 0, NULLCHAR,
  651. #endif
  652.     NULLCHAR
  653. };
  654.  
  655. /* this function is called whenever the forwarding timer expires */
  656. static void
  657. startfwd(a,v1,v2)
  658. int a;
  659. void *v1, *v2;
  660. {
  661.     struct mbx *m;
  662.     char *cc;
  663.     cc = (char *) v1;
  664.     if((m = newmbx()) == NULLMBX) {
  665.         xfree(cc);
  666.         xfree((char *)v2);
  667.         return;
  668.     }
  669.     strcpy(m->name,(char *)v2);
  670.     xfree((char *)v2);
  671.     m->state = MBX_TRYING;
  672.     /* open the connection, m->user will be the new socket */
  673.     if(cmdparse(cfwdcmds,cc,(void *)m) == -1) {
  674.         xfree(cc);
  675.         exitbbs(m);
  676.         return;
  677.     }
  678.     xfree(cc);
  679.     m->state = MBX_FORWARD;
  680.     sockowner(m->user,Curproc);
  681.     close_s(Curproc->output);
  682.     close_s(Curproc->input);
  683.     /* m->user will be closed automatically when this process exits */
  684.     Curproc->output = Curproc->input = m->user;
  685.     /* We'll do our own flushing right before we read input */
  686.     setflush(m->user,-1);
  687.  
  688.     if(fwdinit(m) == -1) {
  689.         /* it is probably not the right time to forward anymore */
  690.         exitbbs(m);
  691.         return;
  692.     }
  693.     /* read the connect script. Lines starting with a dot will be sent
  694.      * to the remote BBS.
  695.      */
  696.     while(fgets(m->line,MBXLINE,m->tfile) != NULLCHAR)
  697.         if(*m->line == '.')
  698.             tputs(m->line + 1);
  699.         else
  700.             break;
  701.     usflush(m->user);
  702.     fclose(m->tfile);
  703.     m->tfile = NULLFILE;
  704.  
  705.     /* read the initial output from the bbs, looking for the SID */
  706.     for(;;) {
  707.         if(recvline(m->user,m->line,MBXLINE) == -1) {
  708.             exitbbs(m);
  709.             return;
  710.         }
  711.         if(ISPROMPT(m->line))
  712.             break;
  713.         if(*m->line == '[') {        /* parse the SID */
  714.             rip(m->line);
  715.             mbx_parse(m);
  716.             continue;
  717.         }
  718.     }
  719.     /* Now sync the two ends as telnet password messes them up */
  720.     if(socklen(m->user,0))        /* discard any remaining input */
  721.         recv_mbuf(m->user,NULL,0,NULLCHAR,0);
  722.  
  723.     /* send our SID if the peer announced its SID */
  724.     if(m->sid & MBX_SID) {
  725.         tputs("[WNOS-H$]\n");
  726.         usflush(m->user);
  727.         for(;;) {
  728.             if(recvline(m->user,m->line,MBXLINE) == -1) {
  729.                 exitbbs(m);
  730.                 return;
  731.             }
  732.             if(ISPROMPT(m->line))
  733.                 break;
  734.         }
  735.     }
  736.     /* start the actual forwarding */
  737.     dorevfwd(0,NULL,(void *)m);
  738.     /* ask for reverse forwarding or just disconnect */
  739.     if(((m->sid & MBX_SID) && tputs("F>\n") == -1) ||
  740.        (m->sid & MBX_SID) == 0) {
  741.         exitbbs(m);
  742.         close_s(Curproc->output);
  743.         return;
  744.     }
  745.     usflush(m->user);
  746.     /* parse the commands that are are received during reverse
  747.      * forwarding.
  748.      */
  749.     while(recvline(m->user,m->line,MBXLINE) > 0) {
  750.         rip(m->line);
  751.         if(mbx_parse(m) == 2)    /* got the "*** Done" command */
  752.             break;
  753.  
  754. // DL8YQ        tputs("F>\n");
  755.         tputs(">\n");
  756.         usflush(m->user);
  757.     }
  758.     exitbbs(m);
  759.     close_s(Curproc->output);
  760. }
  761.  
  762. /* open a network connection based upon information in the cc line.
  763.  * m->user is set to the socket number.
  764.  */
  765. static int
  766. openconn(argc,argv,p)
  767. int argc;
  768. char *argv[];
  769. void *p;
  770. {
  771.     struct mbx *m;
  772.     char sock[MAXSOCKSIZE];
  773. #ifdef NETROM
  774.         char *np, alias[AXBUF];
  775. #endif
  776.     union sp sp;
  777.     int len;
  778.     m = (struct mbx *)p;
  779.     sp.p = sock;
  780.     if(argc < 2)
  781.         return -1;
  782.     switch(*argv[0]) {
  783.     case 't':
  784.         sp.in->sin_family = AF_INET;
  785.         if((sp.in->sin_addr.s_addr = resolve(argv[1])) == 0)
  786.             return -1;
  787.         /* get the optional port number */
  788.         if(argc > 2)
  789.             sp.in->sin_port = atoi(argv[2]);
  790.         else
  791.             sp.in->sin_port = IPPORT_TELNET;
  792.         if((m->user = socket(AF_INET,SOCK_STREAM,0)) == -1)
  793.             return -1;
  794.         len = sizeof(*sp.in);
  795.         break;
  796. #ifdef AX25
  797.     case 'a':
  798.     case 'c':    /* allow 'c' for 'connect' as well */
  799.         if(argc < 3)
  800.             return -1;
  801.         sp.ax->sax_family = AF_AX25;
  802.         strncpy(sp.ax->iface,argv[1],ILEN); /* the interface name */
  803.         setcall(sp.ax->ax25_addr,argv[2]); /* the remote callsign */
  804.         /* no digipeaters for now, use the "ax25 route add" command */
  805.         if((m->user = socket(AF_AX25,SOCK_STREAM,0)) == -1)
  806.             return -1;
  807.         len = sizeof(*sp.ax);
  808.         break;
  809. #endif /* AX25 */
  810. #ifdef NETROM
  811.     case 'n':
  812.         sp.nr->nr_family = AF_NETROM;
  813.         len = sizeof(*sp.nr);
  814.         if((m->user = socket(AF_NETROM,SOCK_SEQPACKET,0)) == -1)
  815.             return -1;
  816.         memcpy(sp.nr->nr_addr.user,Nr4user,AXALEN);
  817.         memcpy(sp.nr->nr_addr.node,Mycall,AXALEN);
  818.         bind(m->user,sp.p,len);
  819.         /* See if the requested destination could be an alias, and
  820.          * use it if it is.  Otherwise assume it is an AX.25
  821.          * address.
  822.          */
  823.         if (putalias(alias,argv[1],0) != -1 &&
  824.             (np = find_nralias(alias)) != NULLCHAR) {
  825.                 memcpy(sp.nr->nr_addr.user,np,AXALEN) ;
  826.                 memcpy(sp.nr->nr_addr.node,np,AXALEN) ;
  827.         }
  828.         else {    /* parse ax25 callsign */
  829.         /* Only the user callsign of the remote station is never
  830.          * used by NET/ROM, but it is needed for the psocket() call.
  831.          */
  832.             setcall(sp.nr->nr_addr.user,argv[1]);
  833.             setcall(sp.nr->nr_addr.node,argv[1]);
  834.         }
  835.         break;
  836. #endif /* NETROM */
  837.     default:
  838.         return -1;
  839.     }
  840.     sockmode(m->user,SOCK_ASCII);
  841.     if(connect(m->user,sp.p,len) == -1) {
  842.         log(m->user,"MBOX forward failed: %s errno %d",
  843.                 sockerr(m->user),errno);
  844.         close_s(m->user);
  845.         return -1;
  846.     }
  847.     return m->user;
  848. }
  849.  
  850.